home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Programming Sound Cards
/
Programming Sound Cards.iso
/
sound_87
/
devsb.pas
< prev
next >
Wrap
Pascal/Delphi Source File
|
1995-01-01
|
31KB
|
1,312 lines
{****************************************************************************}
{ }
{ MODULE: DevSB }
{ }
{ DESCRIPTION: Device driver for the Sound Blaster sound card and }
{ compatibles, including the Sound Blaster Pro, Sound }
{ Booster, etc... }
{ Uses both: DMA and timer polling. }
{ }
{ AUTHOR: Juan Carlos Arévalo }
{ }
{ MODIFICATIONS: Nobody (yet ;-) }
{ }
{ HISTORY: 18-Oct-1992 Documentation. It doesn't allow the stereo }
{ of the SB Pro yet. }
{ 12-Nov-1992 SB Pro driver included. Speed-ups and fixes. }
{ }
{ (C) 1992 VangeliSTeam }
{____________________________________________________________________________}
UNIT DevSB;
INTERFACE
CONST
SBDevID = 'SBlaster-Mono';
DMASBDevID = 'DMA-SB-Mono';
DMASBSterDevID = 'DMA-SB-Stereo';
DMASBMixDevID = 'Mix-DMA-SB-Stereo';
DMASBMix2DevID = 'Mix2-DMA-SB-Stereo';
CONST
SbCmdTimeout : WORD = 100; { $10 DSP Command timeout. }
SbSplTimeout : WORD = 10; { $10 DSP Parameter timeout. }
SbStereoMix : BYTE = 2; { Stereo mixing algorithm. }
SbProMixMasterVol : BYTE = 255; { Master volume of the SB Pro mixer. }
SbProMixDACVol : BYTE = 255; { DAC volume. }
SbProMixFMVol : BYTE = 255; { FM music volume. }
SbProMixFilter : BOOLEAN = FALSE; { TRUE = Activate SB Pro output filter. }
PROCEDURE SBInit (Hz: WORD);
PROCEDURE SBEnd;
IMPLEMENTATION
USES Dos,
SoundDevices, StrConst,
Kbd, Debugging, SoundBlaster, Hardware;
FUNCTION SBName : TDevName; FAR;
BEGIN
SBName := GetString(StrDevSBName);
END;
FUNCTION DMASBName : TDevName; FAR;
BEGIN
DMASBName := GetString(StrDevDMASBName);
END;
FUNCTION DMASBSterName : TDevName; FAR;
BEGIN
DMASBSterName := GetString(StrDevDMASBSterName);
END;
FUNCTION DMASBMixName : TDevName; FAR;
BEGIN
DMASBMixName := GetString(StrDevDMASBMixName);
END;
FUNCTION DMASBMix2Name : TDevName; FAR;
BEGIN
DMASBMix2Name := GetString(StrDevDMASBMix2Name);
END;
{$L DEVSB}
(******)
PROCEDURE SBInit(Hz: WORD);
BEGIN
SbRegInit;
CalcTimerData(Hz);
InitTimer;
END;
PROCEDURE SBIntHandler; FAR; EXTERNAL;
PROCEDURE SBChgHz(Hz: WORD); FAR;
BEGIN
CalcTimerData(Hz);
InitTimer;
END;
PROCEDURE DevPoll; FAR;
BEGIN
END;
PROCEDURE SBEnd;
BEGIN
SbRegDone;
END;
CONST
SBData : TSoundDevice = (
DevID : SBDevID;
DMA : FALSE
);
(******)
FUNCTION GetDMACount : WORD;
VAR
c : BYTE;
BEGIN
PORT[$0C] := 0; {clear BYTE POINTER flip-flop TO lower BYTE}
c := PORT[$03];
GetDMACount := c + 256*WORD(PORT[$03]);
END;
CONST
OldDMAIrq : POINTER = NIL;
DMAPlacedInBuf : WORD = 0;
PROCEDURE DMAIrq; FAR; FORWARD;
PROCEDURE DoDMA; FORWARD;
{
FUNCTION LimitHz(Hz: WORD; Output: BOOLEAN);
BEGIN
IF Hz < 4000 THEN Hz := 4000;
IF (NOT DoHiSpeed) OR (SbStereo AND NOT Sb16Detected) THEN
IF Hz > 23000 THEN Hz := 23000;
LimitHz := Hz;
END;
FUNCTION CalcTimeConst(Hz: WORD) : BYTE;
VAR
TimeConst : BYTE;
BEGIN
Hz := LimitHz(Hz, TRUE);
IF SbStereo AND NOT Sb16Detected THEN
BEGIN
TimeConst := Hi(65536 - 128000000 DIV Hz);
SoundHz := 500000 DIV (256 - WORD(TimeConst));
END
ELSE IF (NOT Sb16Detect) AND (NOT DoHiSpeed) THEN
BEGIN
TimeConst := 256 - 1000000 DIV Hz;
SoundHz := 1000000 DIV (256 - WORD(TimeConst));
END
ELSE
BEGIN
TimeConst := Hi(65536 - 256000000 DIV Hz);
SoundHz := 1000000 DIV (256 - WORD(TimeConst));
END;
CalcTimeConst := TimeConst;
END;
FUNCTION CalcHz(tc: BYTE) : WORD;
VAR
TimeConst : BYTE;
BEGIN
IF (NOT Sb16Detect) AND (NOT DoHiSpeed) THEN
IF SbStereo THEN
Hz := 500000 DIV (256 - WORD(TimeConst))
ELSE
Hz := 1000000 DIV (256 - WORD(TimeConst))
ELSE
Hz := 1000000 DIV (256 - WORD(TimeConst));
CalcHz := Hz;
END;
}
FUNCTION DMASBGetRealFreq(Hz: WORD) : WORD; FAR;
VAR
i : WORD;
NHz1 : WORD;
NHz2 : WORD;
BEGIN
IF Hz < 4000 THEN Hz := 4000;
IF (NOT DoHiSpeed) OR (SbStereo AND NOT Sb16Detected) THEN
IF Hz > 21800 THEN Hz := 21800;
i := Hi(65536 - (256000000 DIV Hz));
NHz1 := 1000000 DIV (256 - i);
NHz2 := 1000000 DIV (256 - i - 1);
IF ABS(INTEGER(NHz1 - Hz)) > ABS(INTEGER(NHz2 - Hz)) THEN NHz1 := NHz2;
DMASBGetRealFreq := NHz1;
END;
FUNCTION DMASBProGetRealFreq(Hz: WORD) : WORD; FAR;
VAR
i : WORD;
NHz1 : WORD;
NHz2 : WORD;
BEGIN
IF Sb16Detected THEN
BEGIN
DMASBProGetRealFreq := DMASBGetRealFreq(Hz);
EXIT;
END;
IF Hz < 4000 THEN Hz := 4000;
IF (NOT DoHiSpeed) OR SbStereo THEN
IF Hz > 21800 THEN Hz := 21800;
i := Hi(65536 - (128000000 DIV Hz));
NHz1 := 500000 DIV (256 - i);
NHz2 := 500000 DIV (256 - i - 1);
IF ABS(INTEGER(NHz1 - Hz)) > ABS(INTEGER(NHz2 - Hz)) THEN NHz1 := NHz2;
DMASBProGetRealFreq := NHz1;
END;
PROCEDURE DMASBCalcTimerData(Hz: WORD);
BEGIN
CalcTimerData(PeriodicHz);
Hz := ActiveDevice^.GetRealFreqProc(Hz);
IF SbStereo AND NOT Sb16Detected THEN
BEGIN
TimeConst := Hi(65536 - 128000000 DIV Hz);
SoundHz := 500000 DIV (256 - WORD(TimeConst));
END
ELSE
BEGIN
TimeConst := Hi(65536 - 256000000 DIV Hz);
SoundHz := 1000000 DIV (256 - WORD(TimeConst));
END;
END;
FUNCTION SbMonoDetect : BOOLEAN; FAR;
BEGIN
SbRegInit;
SbProInit;
Sb16Init;
SbMonoDetect := SbRegDetect;
END;
FUNCTION SbStereoDetect : BOOLEAN; FAR;
BEGIN
SbRegInit;
SbProInit;
Sb16Init;
SbStereoDetect := SbProDetect OR Sb16Detect;
END;
PROCEDURE DMASBInit(Hz: WORD);
BEGIN
SbRegInit;
SbProInit;
Sb16Init;
IF OldDMAIrq = NIL THEN BEGIN
OldDMAIrq := SetIRQVector(SbIrq, @DMAIrq);
EnableIRQ(SbIrq);
END;
DMASet(SbDMAChan, $58, DMABuffer, DMABufferSize);
SbProSetStereo(SbStereo);
DMASBCalcTimerData(Hz);
InitTimer;
SbUpdateTimeConst;
DMAStopped := FALSE;
DMAStop := FALSE;
END;
PROCEDURE DMASBMonoInit(Hz: WORD); FAR;
BEGIN
SbStereo := FALSE;
Sb16Bit := FALSE;
DMASbInit(Hz);
END;
PROCEDURE DMASBSterInit(Hz: WORD); FAR;
BEGIN
SbStereo := TRUE;
Sb16Bit := FALSE;
SbStereoMix := 0;
DMASbInit(Hz);
END;
PROCEDURE DMASBMixInit(Hz: WORD); FAR;
BEGIN
SbStereo := TRUE;
Sb16Bit := FALSE;
SbStereoMix := 1;
DMASbInit(Hz);
END;
PROCEDURE DMASBMix2Init(Hz: WORD); FAR;
BEGIN
SbStereo := TRUE;
Sb16Bit := FALSE;
SbStereoMix := 2;
DMASbInit(Hz);
END;
PROCEDURE DMASBChgHz(Hz: WORD); FAR;
BEGIN
DMASBCalcTimerData(Hz);
END;
PROCEDURE DMASBEnd; FAR;
BEGIN
IF OldDMAIrq <> NIL THEN BEGIN
DMAStopped := FALSE;
DMAStop := TRUE;
ASM PUSHF; STI END;
WHILE (NOT DMAStopped) AND (NOT DeviceIdling) DO;
ASM POPF END;
SetIRQVector(SbIrq, OldDMAIrq);
OldDMAIrq := NIL;
END;
DisableIRQ(SbIrq);
END;
(*
PROCEDURE DMAXchgBuffs; ASSEMBLER;
ASM
MOV DX,WORD PTR [DMABuffer1+2]
MOV SI,WORD PTR [DMABuffer1]
MOV BX,WORD PTR [DMABuffer1Full]
LES DI, [DMABuffer2]
MOV AX,WORD PTR [DMABuffer2Full]
MOV WORD PTR [DMABuffer1],DI
MOV WORD PTR [DMABuffer1+2],ES
MOV WORD PTR [DMABuffer1Full],AX
MOV WORD PTR [DMABuffer2],SI
MOV WORD PTR [DMABuffer2+2],DX
MOV WORD PTR [DMABuffer2Full],BX
END;
*)
(*
PROCEDURE AdjustBufferPointers;
VAR
o : WORD;
BEGIN
o := DMAPlacedInBuf;
IF SbStereo THEN INC(o, o);
IF Sb16Bit THEN INC(o, o);
IF DMABuffer1 = DMABuffer THEN
DMABuffer2 := Ptr(SEG(DMABuffer^),OFS(DMABuffer^) + o)
ELSE
DMABuffer1 := Ptr(SEG(DMABuffer^),OFS(DMABuffer^) + o);
END;
*)
PROCEDURE Dump8Channels; FORWARD;
PROCEDURE DMADoGetBuff; ASSEMBLER;
ASM
{
PUSH 0
PUSH 0
PUSH $FF
CALL SetBorder
}
CALL DoGetBuffer
ADD [DMAPlacedInBuf],AX
{
PUSH 0
PUSH $FF
PUSH 0
CALL SetBorder
MOV AX,[DMAPlacedInBuf]
}
CMP AX,10
JNC @@nofin
{
XOR AX,AX
MOV [DMAPlacedInBuf],AX
}
JMP @@Fin1
@@nofin:
MOV BL,[SbStereo]
AND BL,BL
JZ @@1
ADD AX,AX
@@1:
PUSH AX
CALL GetDMACount
MOV BX,DMABufferSize - 1
SUB BX,AX
ADD BX,WORD PTR [DMABuffer]
MOV CX,BX
SUB BX,WORD PTR [DMABufferPtr]
JNC @@5
ADD BX,DMABufferSize
@@5: POP AX
PUSH AX
SUB BX,AX
JNC @@6
{ INC [PleaseFallBack]}
ADD AX,BX
JNZ @@6
{ DEC [PleaseFallBack]}
POP AX
PUSH AX
@@6:
POP BX
{
PUSH AX
MOV BX,WORD PTR [DMABufferPtr]
SUB BX,CX
JNC @@7
ADD BX,DMABufferSize
@@7: POP AX
SUB BX,AX
JNC @@8
ADD AX,BX
@@8:
}
MOV BL,[SbStereo]
AND BL,BL
JZ @@2
SHR AX,1
@@2:
JMP Dump8Channels
@@Fin1:
END;
PROCEDURE Dump8Channels; ASSEMBLER;
CONST
First : BOOLEAN = TRUE;
ASM
MOV DL,[First]
AND DL,DL
JZ @@nofirst
MOV WORD PTR [CS:@@Data11-2],0
MOV WORD PTR [CS:@@Data12-2],0
MOV WORD PTR [CS:@@Data21-2],0
MOV WORD PTR [CS:@@Data22-2],0
MOV [First],0
@@nofirst:
MOV DL,[DoEqualice]
MOV BYTE PTR [CS:@@Equalice],DL
MOV BL,[SbStereo]
MOV BH,[SbStereoMix]
LES DI,[DMABufferPtr]
MOV CX,[DMABufferEnd]
MOV WORD PTR [CS:@@moData1-2],CX
MOV WORD PTR [CS:@@stData1-2],CX
MOV WORD PTR [CS:@@m1Data1-2],CX
MOV WORD PTR [CS:@@m2Data1-2],CX
LDS SI,[Sounding]
CLD
MOV CX,AX
AND BL,BL
JNZ @@stereo
@@lpfillmono:
MOV AX,[DS:SI]
ADD AX,[DS:SI+6]
ADD AX,[DS:SI+8]
ADD AX,[DS:SI+14]
ADD AX,[DS:SI+16]
ADD AX,[DS:SI+22]
ADD AX,[DS:SI+24]
ADD AX,[DS:SI+30]
MOV BX,[DS:SI+2]
ADD BX,[DS:SI+4]
ADD BX,[DS:SI+10]
ADD BX,[DS:SI+12]
ADD BX,[DS:SI+18]
ADD BX,[DS:SI+20]
ADD BX,[DS:SI+26]
ADD BX,[DS:SI+28]
ADD AX,BX
JNO @@nooverf
JS @@posit
MOV AX,-32768
JMP @@nooverf
@@posit: MOV AX,32767
@@nooverf:
MOV DL,BYTE PTR [CS:@@Equalice]
AND DL,DL
JZ @@noequal
PUSH CX
PUSH AX
CWD
MOV BX,1234
@@Data11:
MOV CX,1234
@@Data12:
SAR CX,1
RCR BX,1
SAR CX,1
RCR BX,1
SUB AX,BX
SBB DX,CX
SAR CX,1
RCR BX,1
SUB AX,BX
SBB DX,CX
MOV WORD PTR [CS:@@Data11-2],AX
MOV WORD PTR [CS:@@Data12-2],DX
MOV BX,AX
MOV CX,DX
POP AX
PUSH BX
PUSH CX
CWD
MOV BX,1234
@@Data21:
MOV CX,1234
@@Data22:
SAR CX,1
RCR BX,1
ADD AX,BX
ADC DX,CX
SAR CX,1
RCR BX,1
ADD AX,BX
ADC DX,CX
SAR CX,1
RCR BX,1
SAR CX,1
RCR BX,1
ADD AX,BX
ADC DX,CX
MOV WORD PTR [CS:@@Data21-2],AX
MOV WORD PTR [CS:@@Data22-2],DX
POP CX
POP BX
SUB AX,BX
SBB DX,CX
SUB AX,BX
SBB DX,CX
SAR DX,1
RCR AX,1
CMP DX,0
JG @@up
JNE @@neg
CMP AX,32768
JC @@nada
@@up: MOV AX,32767
JMP @@nada
@@neg: CMP DX,-1
JNZ @@dw
CMP AX,32768
JNC @@nada
@@dw: MOV AX,-32768
@@nada:
POP CX
@@noequal:
(*
MOV DX,AX
MOV BX,1234
NEG BX
@@Data1:
ADD AX,BX
JNO @@1nooverf
JS @@1posit
MOV AX,-32767
JMP @@1nooverf
@@1posit: MOV AX,32767
@@1nooverf:
{ MOV WORD PTR [CS:@@Data1-2],AX}
XCHG AX,DX
MOV BX,1234
@@Data2:
ADD AX,BX
JNO @@2nooverf
JS @@2posit
MOV AX,-32767
JMP @@2nooverf
@@2posit: MOV AX,32767
@@2nooverf:
{ MOV WORD PTR [CS:@@Data2-2],AX}
SUB AX,DX
JNO @@3nooverf
JS @@3posit
MOV AX,-32767
JMP @@3nooverf
@@3posit: MOV AX,32767
@@3nooverf:
NEG DX
ADD AX,DX
JNO @@4nooverf
JS @@4posit
MOV AX,-32767
JMP @@4nooverf
@@4posit: MOV AX,32767
@@4nooverf:
ADD AX,DX
JNO @@5nooverf
JS @@5posit
MOV AX,-32767
JMP @@5nooverf
@@5posit: MOV AX,32767
@@5nooverf:
*)
XOR AH,80h
MOV AL,AH
STOSB
CMP DI,$1234
@@moData1:
JB @@monocont
SUB DI,DMABufferSize
@@monocont: ADD SI,MaxChannels*2
DEC CX
JNZ @@lpfillmono
{ LOOP @@lpfillmono}
JMP @@Fin
@@Equalice: DB 0
@@stereo: AND BH,BH
JNZ @@domix
@@lpfillster:
MOV AX,[DS:SI]
ADD AX,[DS:SI+6]
ADD AX,[DS:SI+8]
ADD AX,[DS:SI+14]
ADD AX,[DS:SI+16]
ADD AX,[DS:SI+22]
ADD AX,[DS:SI+24]
ADD AX,[DS:SI+30]
MOV BX,[DS:SI+2]
ADD BX,[DS:SI+4]
ADD BX,[DS:SI+10]
ADD BX,[DS:SI+12]
ADD BX,[DS:SI+18]
ADD BX,[DS:SI+20]
ADD BX,[DS:SI+26]
ADD BX,[DS:SI+28]
ADD BX,BX
JNO @@stnooverf1
JS @@stposit1
MOV BX,-32768
JMP @@stnooverf1
@@stposit1: MOV BX,32767
@@stnooverf1:
ADD AX,AX
JNO @@stnooverf2
JS @@stposit2
MOV AX,-32768
JMP @@stnooverf2
@@stposit2: MOV AX,32767
@@stnooverf2:
MOV AL,BH
XOR AX,8080h
STOSW
CMP DI,$1234
@@stData1:
JB @@stercont
SUB DI,DMABufferSize
@@stercont: ADD SI,MaxChannels*2
LOOP @@lpfillster
JMP @@Fin
@@domix: DEC BH
JNZ @@domix2
@@lpfillmix1:
MOV AX,[DS:SI]
ADD AX,[DS:SI+6]
ADD AX,[DS:SI+8]
ADD AX,[DS:SI+14]
ADD AX,[DS:SI+16]
ADD AX,[DS:SI+22]
ADD AX,[DS:SI+24]
ADD AX,[DS:SI+30]
MOV BX,[DS:SI+2]
ADD BX,[DS:SI+4]
ADD BX,[DS:SI+10]
ADD BX,[DS:SI+12]
ADD BX,[DS:SI+18]
ADD BX,[DS:SI+20]
ADD BX,[DS:SI+26]
ADD BX,[DS:SI+28]
MOV DX,AX
ADD AX,BX
JNO @@m1nooverf0
RCR AX,1
JMP @@m1ovc0
@@m1nooverf0: SAR AX,1
@@m1ovc0:
ADD BX,AX
JNO @@m1nooverf1
JS @@m1posit1
MOV BX,-32768
JMP @@m1nooverf1
@@m1posit1: MOV BX,32767
@@m1nooverf1:
ADD AX,DX
JNO @@m1nooverf2
JS @@m1posit2
MOV AX,-32768
JMP @@m1nooverf2
@@m1posit2: MOV AX,32767
@@m1nooverf2:
MOV AL,BH
XOR AX,8080h
STOSW
CMP DI,$1234
@@m1Data1:
JB @@mix1cont
SUB DI,DMABufferSize
@@mix1cont: ADD SI,MaxChannels*2
LOOP @@lpfillmix1
JMP @@Fin
@@domix2:
@@lpfillmix2:
MOV AX,[DS:SI]
ADD AX,[DS:SI+6]
ADD AX,[DS:SI+8]
ADD AX,[DS:SI+14]
ADD AX,[DS:SI+16]
ADD AX,[DS:SI+22]
ADD AX,[DS:SI+24]
ADD AX,[DS:SI+30]
MOV BX,[DS:SI+2]
ADD BX,[DS:SI+4]
ADD BX,[DS:SI+10]
ADD BX,[DS:SI+12]
ADD BX,[DS:SI+18]
ADD BX,[DS:SI+20]
ADD BX,[DS:SI+26]
ADD BX,[DS:SI+28]
SAR BX,1
SAR AX,1
MOV DX,AX
ADD AX,BX
MOV [WORD PTR CS:@@datastm2-2],AX
SAR AX,1
ADD AX,1234
@@datastm2:
JNO @@m2nooverf1
JS @@m2posit1
MOV AX,-32768
JMP @@m2nooverf1
@@m2posit1: MOV AX,32767
@@m2nooverf1:
ADD DX,AX
JNO @@m2nooverf2
JS @@m2posit2
MOV DX,-32768
JMP @@m2nooverf2
@@m2posit2: MOV DX,32767
@@m2nooverf2:
ADD AX,BX
JNO @@m2nooverf3
JS @@m2posit3
MOV AX,-32768
JMP @@m2nooverf3
@@m2posit3: MOV AX,32767
@@m2nooverf3:
MOV AL,DH
XOR AX,8080h
STOSW
CMP DI,$1234
@@m2Data1:
JB @@mix2cont
SUB DI,DMABufferSize
@@mix2cont: ADD SI,MaxChannels*2
LOOP @@lpfillmix2
@@Fin: MOV AX,SEG(@Data)
MOV DS,AX
MOV WORD PTR [DMABufferPtr],DI
{
PUSH 0
PUSH 0
PUSH 0
CALL SetBorder
}
END;
PROCEDURE DoDMA; ASSEMBLER;
CONST
OLDDMABP : WORD = 0;
OLDDMACT : WORD = 0;
ASM
CLI
PUSH BX
PUSH CX
PUSH DX
PUSH DI
PUSH SI
PUSH ES
{
CALL GetDMACount
INC AX
MOV BX,[OLDDMACT]
MOV [OLDDMACT],AX
SUB BX,AX
JNC @@8
ADD BX,DMABufferSize
@@8:
PUSH 0
PUSH BX
PUSH $70
CALL WriteNum
MOV BX,WORD PTR [DMABufferPtr]
MOV AX,[OLDDMABP]
MOV [OLDDMABP],BX
SUB BX,AX
JNC @@9
ADD BX,DMABufferSize
@@9:
PUSH 20
PUSH BX
PUSH $70
CALL WriteNum
}
PUSHA
PUSH 'l'
PUSH $02
CALL WriteChar
POPA
MOV AX,[DMAPlacedInBuf]
AND AX,AX
JNZ @@haybuf
INC [PleaseFallBack]
PUSHA
PUSH 'd'
PUSH $70
CALL WriteChar
POPA
CALL DMADoGetBuff
CALL DMADoGetBuff
MOV AX,[DMAPlacedInBuf]
AND AX,AX
JNZ @@haybuf
INC AH
MOV [DeviceIdling],AH
JMP @@Fin
@@haybuf: XOR BH,BH
MOV [DeviceIdling],BH
CALL SbUpdateTimeConst
MOV CX,[DMAPlacedInBuf]
PUSH CX
PUSH 1
CALL SbPlaySample
XOR AX,AX
MOV [DMAPlacedInBuf],AX
@@7:
CALL DMADoGetBuff
CALL DMADoGetBuff
@@Fin: POP ES
POP SI
POP DI
POP DX
POP CX
POP BX
END;
PROCEDURE DMATim; FAR; ASSEMBLER;
ASM
CLI
PUSH AX
PUSH DS
PUSH ES
MOV AX,SEG(@Data)
MOV DS,AX
PUSHA
PUSH 't'
PUSH $20
CALL WriteChar
POPA
MOV AL,[DMAIrqWatch]
CMP AL,20
JNC @@dowatch
MOV AL,[DeviceIdling]
AND AL,AL
JZ @@notneeded
PUSHA
CALL InitTimer
POPA
JMP @@noack
@@dowatch:
PUSH DX
MOV DX,[DSP8AckPort]
IN AL,DX
MOV DX,[DSPLifePort]
IN AL,DX
POP DX
@@noack: MOV AL,[DMAStop]
AND AL,AL
JZ @@notstop
MOV [DMAStopped],AL
MOV [DeviceIdling],AL
JMP @@notneeded
@@notstop: XOR AL,AL
MOV [DeviceIdling],AL
CALL DoDMA
XOR AL,AL
MOV [DMAIrqWatch],AL
@@notneeded: MOV AL,[DMAIrqWatch]
CMP AL,100
JNC @@noinc
INC [DMAIrqWatch]
@@noinc: MOV AX,[SystemClockIncr]
ADD [SystemClockCount],AX
JNC @@nosys
PUSHF
CALL CSOldInt8
JMP @@sisys
@@nosys: MOV AL,20h
OUT 20h,AL
@@sisys: STI
MOV AL,[DMAStop]
AND AL,AL
JZ @@notstop2
MOV [DMAStopped],AL
MOV [DeviceIdling],AL
JMP @@donothing
@@notstop2: PUSHA
CALL PeriodicProc
MOV AX,[DMAPlacedInBuf]
AND AX,AX
JNZ @@nogetbuff
CLI
CALL DMADoGetBuff
STI
@@nogetbuff:
POPA
@@donothing:
POP ES
POP DS
POP AX
IRET
END;
PROCEDURE DMAIrq; ASSEMBLER;
CONST
Old83 : BYTE = 0;
ASM
CLI
PUSH DX
PUSH AX
PUSH DS
PUSH ES
MOV AX,SEG(@Data)
MOV DS,AX
{
MOV DX,[MixAddrPort]
MOV AL,$83
OUT DX,AL
INC DL
IN AL,DX
MOV [Old83],AL
DEC DL
MOV AL,$83
OUT DX,AL
INC DL
XOR AL,AL
OUT DX,AL
}
MOV DX,[DSP8AckPort]
IN AL,DX
MOV DX,[DSPLifePort]
IN AL,DX
PUSHA
PUSH 'i'
PUSH $07
CALL WriteChar
POPA
XOR AL,AL
MOV [DMAIrqWatch],AL
MOV AL,[DMAStop]
AND AL,AL
JZ @@nostop
MOV [DMAStopped],AL
MOV [DeviceIdling],AL
JMP @@Fin
@@nostop:
CALL DoDMA
@@Fin:
{
PUSHA
PUSH 100
PUSH $DA
CALL SbWriteByte
POPA
PUSHA
PUSH 100
PUSH $45
CALL SbWriteByte
POPA
}
{
MOV DX,[MixAddrPort]
MOV AL,$83
OUT DX,AL
INC DL
MOV AL,[Old83]
OUT DX,AL
}
MOV AX,[SbIrq]
CMP AL,10
JNZ @@not10
MOV AL,$20
OUT $A0,AL
@@not10: MOV AL,$20
OUT $20,AL
POP ES
POP DS
POP AX
POP DX
IRET
END;
CONST
DMASBData : TSoundDevice = (
DevID : DMASBDevID;
DMA : TRUE
);
CONST
DMASBSterData : TSoundDevice = (
DevID : DMASBSterDevID;
DMA : TRUE
);
CONST
DMASBMixData : TSoundDevice = (
DevID : DMASBMixDevID;
DMA : TRUE
);
CONST
DMASBMix2Data : TSoundDevice = (
DevID : DMASBMix2DevID;
DMA : TRUE
);
(******)
BEGIN
WITH SBData DO BEGIN
Name := SBName;
AutoDetect := SbRegDetect;
InitRut := SBInit;
ChgHzProc := SBChgHz;
GetRealFreqProc := GetRealFreq;
TimerHandler := SBIntHandler;
PollRut := DevPoll;
EndRut := SBEnd;
END;
WITH DMASBData DO BEGIN
Name := DMASBName;
AutoDetect := SbMonoDetect;
InitRut := DMASBMonoInit;
ChgHzProc := DMASBChgHz;
GetRealFreqProc := DMASBGetRealFreq;
TimerHandler := DMATim;
PollRut := DevPoll;
EndRut := DMASBEnd;
END;
WITH DMASBSterData DO BEGIN
Name := DMASBSterName;
AutoDetect := SbStereoDetect;
InitRut := DMASBSterInit;
ChgHzProc := DMASBChgHz;
GetRealFreqProc := DMASBProGetRealFreq;
TimerHandler := DMATim;
PollRut := DevPoll;
EndRut := DMASBEnd;
END;
WITH DMASBMixData DO BEGIN
Name := DMASBMixName;
AutoDetect := SbStereoDetect;
InitRut := DMASBMixInit;
ChgHzProc := DMASBChgHz;
GetRealFreqProc := DMASBProGetRealFreq;
TimerHandler := DMATim;
PollRut := DevPoll;
EndRut := DMASBEnd;
END;
WITH DMASBMix2Data DO BEGIN
Name := DMASBMix2Name;
AutoDetect := SbStereoDetect;
InitRut := DMASBMix2Init;
ChgHzProc := DMASBChgHz;
GetRealFreqProc := DMASBProGetRealFreq;
TimerHandler := DMATim;
PollRut := DevPoll;
EndRut := DMASBEnd;
END;
InitDevice(@DMASBMix2Data);
InitDevice(@DMASBMixData);
InitDevice(@DMASBSterData);
InitDevice(@DMASBData);
InitDevice(@SBData);
END.